package com.voicecomm.audio;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 音频录制器
 * 负责从麦克风录制音频数据
 * 
 * @author VoiceComm Team
 * @version 1.0.0
 */
public class AudioRecorder {
    
    private static final Logger logger = LoggerFactory.getLogger(AudioRecorder.class);
    
    // 音频格式配置
    private static final AudioFormat AUDIO_FORMAT = new AudioFormat(
        AudioFormat.Encoding.PCM_SIGNED,  // 编码格式
        16000.0f,                        // 采样率
        16,                              // 采样位数
        1,                               // 声道数
        2,                               // 帧大小
        16000.0f,                        // 帧率
        false                            // 小端序
    );
    
    private TargetDataLine targetDataLine;
    private final AtomicBoolean isRecording = new AtomicBoolean(false);
    private ByteArrayOutputStream audioBuffer;
    private Thread recordingThread;
    
    /**
     * 初始化音频录制器
     * 
     * @throws LineUnavailableException 音频设备不可用异常
     */
    public void initialize() throws LineUnavailableException {
        DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, AUDIO_FORMAT);
        
        if (!AudioSystem.isLineSupported(dataLineInfo)) {
            throw new LineUnavailableException("音频格式不支持");
        }
        
        targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
        targetDataLine.open(AUDIO_FORMAT);
        
        logger.info("音频录制器初始化成功，采样率: {}Hz, 位深: {}bit", 
                   AUDIO_FORMAT.getSampleRate(), AUDIO_FORMAT.getSampleSizeInBits());
    }
    
    /**
     * 开始录制音频
     * 
     * @param audioDataCallback 音频数据回调接口
     */
    public void startRecording(AudioDataCallback audioDataCallback) {
        if (isRecording.get()) {
            logger.warn("音频录制已在进行中");
            return;
        }
        
        try {
            targetDataLine.start();
            isRecording.set(true);
            audioBuffer = new ByteArrayOutputStream();
            
            // 创建录制线程
            recordingThread = new Thread(() -> {
                byte[] buffer = new byte[4096];
                int bytesRead;
                
                logger.info("开始录制音频...");
                
                while (isRecording.get() && targetDataLine.isOpen()) {
                    bytesRead = targetDataLine.read(buffer, 0, buffer.length);
                    if (bytesRead > 0) {
                        // 将音频数据写入缓冲区
                        audioBuffer.write(buffer, 0, bytesRead);
                        
                        // 回调处理音频数据
                        if (audioDataCallback != null) {
                            byte[] audioData = new byte[bytesRead];
                            System.arraycopy(buffer, 0, audioData, 0, bytesRead);
                            audioDataCallback.onAudioData(audioData);
                        }
                    }
                }
                
                logger.info("音频录制结束");
            });
            
            recordingThread.start();
            
        } catch (Exception e) {
            logger.error("启动音频录制失败", e);
            isRecording.set(false);
        }
    }
    
    /**
     * 停止录制音频
     */
    public void stopRecording() {
        if (!isRecording.get()) {
            logger.warn("音频录制未在进行中");
            return;
        }
        
        isRecording.set(false);
        
        if (targetDataLine != null && targetDataLine.isOpen()) {
            targetDataLine.stop();
            targetDataLine.close();
        }
        
        if (recordingThread != null) {
            try {
                recordingThread.join(1000); // 等待最多1秒
            } catch (InterruptedException e) {
                logger.warn("等待录制线程结束被中断", e);
                Thread.currentThread().interrupt();
            }
        }
        
        logger.info("音频录制已停止");
    }
    
    /**
     * 获取录制的音频数据
     * 
     * @return 音频数据字节数组
     */
    public byte[] getAudioData() {
        if (audioBuffer != null) {
            return audioBuffer.toByteArray();
        }
        return new byte[0];
    }
    
    /**
     * 获取音频格式
     * 
     * @return 音频格式对象
     */
    public AudioFormat getAudioFormat() {
        return AUDIO_FORMAT;
    }
    
    /**
     * 检查是否正在录制
     * 
     * @return true如果正在录制，false否则
     */
    public boolean isRecording() {
        return isRecording.get();
    }
    
    /**
     * 释放资源
     */
    public void cleanup() {
        stopRecording();
        
        if (audioBuffer != null) {
            try {
                audioBuffer.close();
            } catch (IOException e) {
                logger.warn("关闭音频缓冲区失败", e);
            }
        }
        
        logger.info("音频录制器资源已释放");
    }
    
    /**
     * 音频数据回调接口
     */
    @FunctionalInterface
    public interface AudioDataCallback {
        /**
         * 当接收到音频数据时调用
         * 
         * @param audioData 音频数据字节数组
         */
        void onAudioData(byte[] audioData);
    }
}
